use std::{
    collections::VecDeque,
    io,
    ops::Deref,
    sync::{Arc, Mutex},
};

use mio::{Registry, Token as MioToken, Waker};

use crate::worker::WorkerHandleAccept;

pub(crate) const WAKER_TOKEN: MioToken = MioToken(usize::MAX);

pub(crate) enum WakerInterest {
    WorkerAvailable(usize),
    Pause,
    Resume,
    Stop,
    Woker(WorkerHandleAccept),
}

pub(crate) struct WakerQueue(Arc<(Waker, Mutex<VecDeque<WakerInterest>>)>);

impl Clone for WakerQueue {
    fn clone(&self) -> Self {
        Self(self.0.clone())
    }
}

impl Deref for WakerQueue {
    type Target = (Waker, Mutex<VecDeque<WakerInterest>>);
    fn deref(&self) -> &Self::Target {
        self.0.deref()
    }
}

impl WakerQueue {
    pub(crate) fn new(registry: &Registry) -> io::Result<Self> {
        let waker = Waker::new(registry, WAKER_TOKEN)?;
        let queue = Mutex::new(VecDeque::with_capacity(16));
        Ok(Self(Arc::new((waker, queue))))
    }

    pub(crate) fn wake(&self, interest: WakerInterest) {
        let (waker, queue) = self.deref();
        // 压入队列
        queue
            .lock()
            .expect("Failed to lock WakerQueue")
            .push_back(interest);
        // 唤醒
        waker
            .wake()
            .unwrap_or_else(|e| panic!("can not wake up Accept Poll: {}", e))
    }
}
